package com.example.springboot;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.action.bind.method.CurrentUserMethodArgumentResolver;
import com.action.dialect.MyStringHandlerDialect;
import com.action.filter.SysUserFilter;
import com.action.realm.UserRealm;
import com.action.service.UserService;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by tang on 2017/11/15.
 */
@ComponentScan(basePackages = {"com"})
@SpringBootApplication
public class App extends WebMvcConfigurerAdapter {

    @Value("${web.img-path-prefix}")
    private String uploadImgPathPrefix;

    @Value("${web.upload-path}")
    private String filePath;

    @Autowired
    private UserService userService;

    /**
     * 在这里我们使用 @Bean注入 fastJsonHttpMessageConvert
     *
     * @return
     */
  /*  @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 1、需要先定义一个 convert 转换消息的对象;
        super.configureMessageConverters(converters);
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();

        //2、添加fastJson 的配置信息，比如：是否要格式化返回的json数据;
        List<MediaType> fastMediaTypes = new ArrayList<MediaType>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);

        //3、在convert中添加配置信息.
        fastConverter.setSupportedMediaTypes(fastMediaTypes);

        converters.add(fastConverter);
    }*/

    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    @Bean
    public UserRealm myShiroRealm() {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        securityManager.setCacheManager(ehCacheManager());
        return securityManager;
    }

    @Bean
    public SysUserFilter sysUserFilter() {
        SysUserFilter sysUserFilter = new SysUserFilter();
        sysUserFilter.setUserService(userService);
        return sysUserFilter;
    }

  /*  @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
        SysUserFilter sysUserFilter = new SysUserFilter();
        sysUserFilter.setUserService(userService);
        filtersMap.put("sysUser", sysUserFilter);
        shiroFilterFactoryBean.setFilters(filtersMap);

        Map<String, String> map = new HashMap<String, String>();
        //登出
        map.put("/logout", "logout");
        //对所有用户认证
        map.put("*/

    /**
     * ", "authc,sysUser");
     * map.put("/login", "authc");
     * map.put("/authenticated", "authc");
     * //登录
     * shiroFilterFactoryBean.setLoginUrl("/login");
     * //首页
     * shiroFilterFactoryBean.setSuccessUrl("/index");
     * //错误页面，认证不通过跳转
     * shiroFilterFactoryBean.setUnauthorizedUrl("/error");
     * shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
     * return shiroFilterFactoryBean;
     * }
     */


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2);// 散列的次数，比如散列两次，相当于md5(md5(""));
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);//表示是否存储散列后的密码为16进制，需要和生成密码时的一样，默认是base64；
        return hashedCredentialsMatcher;
    }


    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
        return cacheManager;
    }


    @Bean
    public MyStringHandlerDialect myStringHandlerDialect() {
        return new MyStringHandlerDialect();
    }

//    @Order(2)
//    @Bean
//    public SpringUtils springUtils(){
//        return  new SpringUtils();
//    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(uploadImgPathPrefix + "**").addResourceLocations("classpath:" + uploadImgPathPrefix).
                addResourceLocations("file:" + filePath);
        super.addResourceHandlers(registry);
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
        argumentResolvers.add(new CurrentUserMethodArgumentResolver());
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(App.class, args);
    }
}
